#ifndef TD_CREEP_MANAGER
#define TD_CREEP_MANAGER

/************************************************************************/
/* Core                                                                 */
/************************************************************************/
#include "Core/Singleton.h"
#include "Core/Timer.h"

/************************************************************************/
/* GUI                                                                  */
/************************************************************************/
#include "GUI/TextMessages/GoldMessage.h"

/************************************************************************/
/* Game                                                                 */
/************************************************************************/
#include "Core/Manager.h"
#include "Game/Factories/MarioFactory.h"
#include "Game/Tilemaps/TerrainTilemap.h"
#include "Game/WaveInfo.h"

using namespace std;
using namespace TD_Core;
using namespace TD_Resources;


namespace TD_Game {


	class MarioManager : public Manager<BaseMario>, public Singleton<MarioManager> {

		/************************************************************************/
		/* Definitions                                                          */
		/************************************************************************/

		bool m_updateMarios;

		static const Coord2D endOfMap;

		Coord2D m_startingPosition;

		Coord2D m_endingPosition;

		TerrainTilemap * m_pTerrain;

		baseMarioDirection m_spawnDirection;
		
		int m_spawnInterval;
		
		unsigned int m_numberOfMarios;
		
		unsigned int m_maxMarios;

		vector<BaseMario *> m_mariosWithinRadius; 

		map<unsigned int, GoldMessage *> m_goldMessages;
		
		Color m_goldColor;
		

		shared_ptr<SDLSound> m_pCoinSound;

		int m_lastTick;

		int m_goldGained;

		int m_mariosPassed;

		WaveInfo m_currWaveInfo;

		bool m_finishedSpawning;

      Timer m_spawnDelay;

		BaseMario *m_pLastSpawnedMario;

		void createGoldMessages(unsigned int baseMarioID, BaseMario * pMario);

		int generateSmallDeviant(unsigned int);

		void deleteMario(map<unsigned int, BaseMario *>::iterator &iter);

	public:

		

		/************************************************************************/
		/* Access functions                                                     */
		/************************************************************************/
		

		/************************************************************************/
		/* Funcionalities                                                       */
		/************************************************************************/
		//Configs creep spawning
		void configSpawning(TerrainTilemap * g_pTerrain, const Coord2D &position ,const WaveInfo &waveInfo);
		//Renders
		void render(SDL_Surface *const g_destSurface, unsigned int deltaTime);
		//Updates
		void update(int deltaTime);
		//Clear the creeps
		void clear();


	public:

		/************************************************************************/
		/* Ctors and dtors                                                      */
		/************************************************************************/
		
		//Default
		MarioManager();

		//Copy
		MarioManager(const MarioManager &rhs);

		//Assignment
		MarioManager & operator=(const MarioManager &rhs);

		//Destructor
		~MarioManager();
		

		/************************************************************************/
		/* Access functions                                                     */
		/************************************************************************/

		inline BaseMario * getMarioByID(unsigned int baseMarioID) {
			return(getObject(baseMarioID));
		}

		const vector<BaseMario *> & getMariosWithinRadius(const Coord2D &position, unsigned int radius);

		inline unsigned int getNumberOfMarios() {
			return(m_objMap.size());
		}

		inline unsigned int getGoldGained() const {
			return(m_goldGained);
		}

		inline void resetGoldGained() {
			m_goldGained = 0;
		}


		inline unsigned int getMariosPassed() const {
			return(m_mariosPassed);
		}

		inline bool finishedSpawning() const {
			return(m_finishedSpawning);
		}

		inline void updateMarios(bool updateMarios) {
			m_updateMarios = updateMarios;
		}
	};

}
#endif	
